/******************************************************************************
 * Encryptor class encrypts messages decryptable by the Decryptor class. It
 * uses OpenSSL enveloping to RSA-encrypt one-time symmetric session keys. The
 * session key is used to encrypt the payload. This work was done for Zero Leak
 * Architecture implementation for Dr. Hiroshi Fujinoki.
 *
 * Usage: Instantiated Encryptor must make the following calls in order:
 * keySrcFiles(...), encryptSessionKeys(), encrypt(...).
 *****************************************************************************/
#ifndef ENCRYPTOR_H_
#define ENCRYPTOR_H_

#include <cstdio>
#include <cstring>
#include <openssl/ssl.h>
#include <openssl/rand.h>

#define BUF_SIZE			2188
#define AES_256_BLOCK_SIZE	32

class Encryptor {
public:
	explicit Encryptor(const char** rsa_keyfiles, const char** expected_CN, int num_keys, const EVP_CIPHER* cipher = EVP_aes_256_cbc());
	virtual ~Encryptor();

	unsigned char* MakeEncryptedPacket(unsigned char* msg, int msg_len, int* encrypt_len);
	unsigned char* encrypt(unsigned char* msg, int msg_len, int* encrypt_len);

	int getSessionKeyLength(int i) const;
	unsigned char* getSessionKey(int i) const;
	unsigned char* getInitVector() const;

private:
	Encryptor(Encryptor&);
	Encryptor& keySrcFiles(const char** rsa_keyfiles, int num_keys);
	Encryptor& setupSessionKeys(const char** commonName);

	EVP_CIPHER_CTX* ctx;			// context
	const EVP_CIPHER* type;			// symmetric cipher
	unsigned char* iv;				// initialization vector
	const char** pubk_files;		// rsa public key files
	unsigned char** ek;				// encrypted session keys
	int* ekl;						// length of each of ek
	EVP_PKEY** pubk;				// public keys
	//RSA** rsa_keys;					// owned by pubk
	int npubk;						// number of public keys
};

#endif /* ENCRYPTOR_H_ */
